其他
求你了,别再用 print 调试代码了
The following article is from Python编程时光 Author 写代码的明哥
如果你是刚接触编程的小萌新,对很多工具的使用还不是很熟练,那么 print 和 log 大法好
如果你在本地(Win或者Mac)电脑上开发,那么 IDE 的图形化界面调试无疑是最适合的;
如果你在服务器上排查BUG,那么使用 PDB 进行无图形界面的调试应该是首选。
如果你要在本地进行开发,但是项目的进行需要依赖复杂的服务器环境,那么可以了解下 PyCharm 的远程调试。
PySnooper
,它在 Github 上已经收到了 13k 的 star,获得大家的一致好评。有了这个工具后,就算是小萌新也可以直接无门槛上手,从此与 print 说再见~1. 快速安装
# 或者
$ conda install -c conda-forge pysnooper
# 或者
$ yay -S python-pysnooper
2. 简单案例
@pysnooper.snoop()
def demo_func():
profile = {}
profile["name"] = "写代码的明哥"
profile["age"] = 27
profile["gender"] = "male"
return profile
def main():
profile = demo_func()
main()
Source path:... demo.py
17:52:49.624943 call 4 def demo_func():
17:52:49.625124 line 5 profile = {}
New var:....... profile = {}
17:52:49.625156 line 6 profile["name"] = "写代码的明哥"
Modified var:.. profile = {'name': '写代码的明哥'}
17:52:49.625207 line 7 profile["age"] = 27
Modified var:.. profile = {'name': '写代码的明哥', 'age': 27}
17:52:49.625254 line 8 profile["gender"] = "male"
Modified var:.. profile = {'name': '写代码的明哥', 'age': 27, 'gender': 'male'}
17:52:49.625306 line 10 return profile
17:52:49.625344 return 10 return profile
Return value:.. {'name': '写代码的明哥', 'age': 27, 'gender': 'male'}
Elapsed time: 00:00:00.000486
代码的片段、行号等信息,以及每一行代码是何时调用的?
函数内局部变量的值如何变化的?何时新增了变量,何时修改了变量。
函数的返回值是什么?
运行函数消耗了多少时间?
@pysnooper.snoop()
即可。3. 详细使用
2.1 重定向到日志文件
@pysnooper.snoop()
不加任何参数时,会默认将调试的信息输出到标准输出。对于单次调试就能解决的 BUG ,这样没有什么问题,但是有一些 BUG 只有在特定的场景下才会出现,需要你把程序放在后面跑个一段时间才能复现。这种情况下,你可以将调试信息重定向输出到某一日志文件中,方便追溯排查。def demo_func():
...
2.2 跟踪非局部变量值
pysnooper.snoop()
加上 watch
参数@pysnooper.snoop(watch=('out["foo"]'))
def demo_func():
...
out["foo"]
值有变化时,也将其打印出来def demo_func():
...
watch
相对的,pysnooper.snoop()
还可以接收一个函数 watch_explode
,表示除了这几个参数外的其他所有全局变量都监控。def demo_func():
...
2.3 设置跟踪函数的深度
depth
参数来设置跟踪深度(不指定的话默认为 1)。def demo_func():
...
2.4 设置调试日志的前缀
def demo_func():
...
2.5 设置最大的输出长度
def demo_func():
...
def demo_func():
...
2.6 支持多线程调试模式
thread_info=True
,它就会在日志中打印出是在哪个线程对变量进行的修改。def demo_func():
...
2.7 自定义对象的格式输出
pysnooper.snoop()
函数有一个参数是 custom_repr
,它接收一个元组对象。在这个元组里,你可以指定特定类型的对象以特定格式进行输出。这边我举个例子。假如我要跟踪 person 这个 Person 类型的对象,由于它不是常规的 Python 基础类型,PySnooper 是无法正常输出它的信息的。因此我在 pysnooper.snoop()
函数中设置了 custom_repr
参数,该参数的第一个元素为 Person,第二个元素为 print_persion_obj
函数。PySnooper 在打印对象的调试信息时,会逐个判断它是否是 Person 类型的对象,若是,就将该对象传入 print_persion_obj
函数中,由该函数来决定如何显示这个对象的信息。def print_person_obj(obj):
return f"<Person {obj.name} {obj.age} {obj.gender}>"
@pysnooper.snoop(custom_repr=(Person, print_person_obj))
def demo_func():
...
class Person:pass
def print_person_obj(obj):
return f"<Person {obj.name} {obj.age} {obj.gender}>"
@pysnooper.snoop(custom_repr=(Person, print_person_obj))
def demo_func():
person = Person()
person.name = "写代码的明哥"
person.age = 27
person.gender = "male"
return person
def main():
profile = demo_func()
main()
custom_repr
参数的值可以这么写def demo_func():
...
@pysnooper.snoop(custom_repr=(Person, print_persion_obj))
def demo_func():
...
# 【第二种写法】
def is_persion_obj(obj):
return isinstance(obj, Person)
@pysnooper.snoop(custom_repr=(is_persion_obj, print_persion_obj))
def demo_func():
...
# 【第三种写法】
@pysnooper.snoop(custom_repr=(lambda obj: isinstance(obj, Person), print_persion_obj))
def demo_func():
...
PySnooper
) 的详细使用手册,是不是觉得还不错?1. 扫描关注下方公众号「GitHuboy」
2. 回复关键词:统计思维导图
推荐阅读
30000字 Matplotlib 实操干货,38个案例带你从入门到进阶! 太香了!最强的 pandas 入门教程 安利3个Python数据分析EDA神器!
骚操作!嵌套 JSON 秒变 Dataframe! 计算机专业几本必看的书! 太强了!一款如操作Excel一样的pandas可视化神器来了! 两篇毕业论文致谢同一个女朋友?哈哈哈哈! 太震撼了!我用Python画出全北京的公交线路动图
🧐分享、点赞、在看,给个三连击呗!👇